/*
 *
 * 名称：五运六气
 * 功能：根据当前时间，计算五运六气各元素值
 * 作者：清河张
 * 时间：2025.05.11
 *
 */

#include "wuyunliuqi.h"
#include <cstdio>


char WUYUNLIUQI::_show[64];

WUYUNLIUQI::WUYUNLIUQI(const LIFA &lf):
    _lf(lf), _yun(0), _qi(0), _suiqi(0), _yun5r(0), _qi6r(0)
{
    if(lf.dateTime().isValid())
    {
        int sui = lf.sui360();
        if(lf.jieqi().jie() < JIEQI_T::DAHAN) sui -= 1;

        const GANZHI suigz = GANZHI::gz60(sui);
        suiyun(suigz._g, &_swx, &_syy, &_sts);
        suiqi(suigz._z, &_suiqi);

        __yqjs();
        __yun5();
        __qi6();
    }
}

qreal WUYUNLIUQI::yun5r() const
{
    return _yun5r;
}

qreal WUYUNLIUQI::qi6r() const
{
    return _qi6r;
}

void WUYUNLIUQI::suiyun(const GAN10 &g, WUXING5 *wx, YY *yy, YY *ts)
{
    WUXING5 wx0 = g.he5(nullptr);
    YY yy0 = g.yy();
    YY ts0 = g.ts();

    if(wx) *wx = wx0;
    if(yy) *yy = yy0;
    if(ts) *ts = ts0;
}

const char *WUYUNLIUQI::suiyun(int id)
{
    GAN10 g = id;
    WUXING5 wx = g.he5(nullptr);
    YY yy = g.yy();

    std::snprintf(_show, sizeof(_show), "%s%s",
                  yy.tsname(),
                  wx.yinname() );

    return _show;
}

const char *WUYUNLIUQI::suiyun() const
{
    std::snprintf(_show, sizeof(_show), "%s%s(%s%s)",
                  _syy.tsname(), _swx.yinname(),
                  _swx.name(), _syy.qrname());
    return _show;
}

void WUYUNLIUQI::suiyun(WUXING5 *wx, YY *yy, YY *ts) const
{
    if(wx) *wx = _swx;
    if(yy) *yy = _syy;
    if(ts) *ts = _sts;
}


const char *WUYUNLIUQI::zhuyun(int zy) const
{
    if(zy < 0) zy = _yun;
    WUXING5 wx = zy;
    YY yy = _sts.fan( zy );//最终阴阳

    std::snprintf(_show, sizeof(_show), "%s%s",
                  yy.tsname(), wx.yinname());
    return _show;
}

void WUYUNLIUQI::zhuyun(WUXING5 *wx, YY *yy) const
{
    if(wx) *wx = _yun;
    if(yy) *yy = _sts.fan( _yun );
}

const char *WUYUNLIUQI::keyun(int ky) const
{
    if(ky < 0) ky = _yun;
    YY yy = _syy.fan( ky );//最终阴阳
    WUXING5 wx = _swx + ky;

    std::snprintf(_show, sizeof(_show), "%s%s",
                  yy.tsname(), wx.yinname());
    return _show;
}

void WUYUNLIUQI::keyun(WUXING5 *wx, YY *yy) const
{
    if(wx) *wx = _swx + _yun;
    if(yy) *yy = _syy.fan( _yun );
}


const QDateTime& WUYUNLIUQI::yqjiaosi() const
{
    return _yqjiaosi;
}


qreal WUYUNLIUQI::jszhoulv() const
{
    return _jszl;
}


void WUYUNLIUQI::suiqi(const ZHI12 &z, int *sq)
{
    int suiqi;
    suiqi = ( z ).id() % 6;
    if(sq) * sq = suiqi;
}

const char *WUYUNLIUQI::suiqi(int z)
{
    std::snprintf(_show, sizeof(_show), "%s",
                      YY6QI6::fromkq(( z + 12 ) % 6).name() );

    return _show;
}

const char *WUYUNLIUQI::suiqi() const
{
    std::snprintf(_show, sizeof(_show), "%s",
                  YY6QI6::fromkq(( _suiqi + 12 ) % 6).name() );

    return _show;
}

void WUYUNLIUQI::suiqi(YY6QI6& yy6qi) const
{
    yy6qi = YY6QI6::fromkq(_suiqi);
}

const char *WUYUNLIUQI::zhuqi(int qi) const
{
    if(qi < 0) qi = _qi;
    std::snprintf(_show, sizeof(_show), "%s",
                  YY6QI6::fromzq(qi).name());
    return _show;
}

void WUYUNLIUQI::zhuqi(YY6QI6 &yy6qi) const
{
    yy6qi = YY6QI6::fromzq(_qi);
}

const char *WUYUNLIUQI::keqi(int qi) const
{
    if(qi < 0) qi = _qi;
    std::snprintf(_show, sizeof(_show), "%s",
                  YY6QI6::fromkq(qi + _suiqi).name() );
    return _show;
}

void WUYUNLIUQI::keqi(YY6QI6 &yy6qi) const
{
    yy6qi = YY6QI6::fromkq(_qi + _suiqi);
}

const char *WUYUNLIUQI::jialin() const
{
    int zx, kx;
    zx = YY6QI6::fromzq(_qi).id();
    kx = YY6QI6::fromkq(_qi + _suiqi).id();

    std::snprintf(_show, sizeof(_show), "%s上逢%s",
                  LIUQI6(zx).name(),
                  LIUQI6(kx).name());
    return _show;
}


const char *WUYUNLIUQI::sitian() const
{
    std::snprintf(_show, sizeof(_show), "%s",
                  YY6QI6::fromkq(2 + _suiqi).name() );
    return _show;
}

const char *WUYUNLIUQI::zaiquan() const
{
    std::snprintf(_show, sizeof(_show), "%s",
                  YY6QI6::fromkq(5 + _suiqi).name() );
    return _show;
}

int WUYUNLIUQI::sizai(YY6QI6 &yy6qi) const
{
    int ret;
    if(_qi < 3)
    {
        ret = 0;
        yy6qi = YY6QI6::fromkq(2 + _suiqi);
    }
    else
    {
        ret = 1;
        yy6qi = YY6QI6::fromkq(5 + _suiqi);
    }
    return ret;
}

void WUYUNLIUQI::__yqjs()
{
    qint64 seconds;
    QDateTime dz = LIFA::jq2datetime(_lf.jieqi().xiangqian(JIEQI_T::DONGZHI));
    QDateTime js = LIFA::jq2datetime(_lf.jieqi().xiangqian(JIEQI_T::DAHAN));
    js.setTime(QTime(ZHI12(ZHI_T::YINN).j1(),0,0));//大寒寅时初初刻
    _yqjiaosi = js.addSecs( ( _lf.sui360() % 4 ) * ( 24 * 60 * 60 / 4 ) );//当年首运
    seconds = dz.secsTo(_yqjiaosi);
    _jszl = qreal(seconds) / ( 24 * 60 * 60 * 365.25 );
}


void WUYUNLIUQI::__yun5()
{
    int seconds;
    constexpr int length = 24 * 60 * 60 * ( 365.25 / 5.0 );

    QDateTime tm2 = _lf.dateTime();
    // QString s = tm1.toString("yyyy-MM-dd HH:mm:ss ") + tm2.toString("yyyy-MM-dd HH:mm:ss ");
    seconds = _yqjiaosi.secsTo(tm2);
    _yun5r = qreal(seconds) / length;
    _yun = (int)_yun5r;
}


void WUYUNLIUQI::__qi6()
{
    int qiid, zjie;
    constexpr double SHCH = ( 365.25 / 6.0 - 60.0 ) * 24.0;
    qint64 secpart, secall;
    JIE24 jsjq;//当前节气、交司节气
    QTime cTime;//指定时刻
    QDateTime laterjs, beforejs, now;//下一交司、上一交司、当前时间
    now = _lf.dateTime();
    zjie = _lf.jieqi().zhoujie();

    jsjq = ( zjie - JIEQI_T::DAHAN ) / 4 * 4 + JIEQI_T::DAHAN;
    qiid = ( zjie - JIEQI_T::DAHAN ) % 24 / 4;

    QDateTime jsdt = LIFA::jq2datetime(jsjq);//节气交接时间
    cTime = _yqjiaosi.time().addSecs( 3600 * SHCH * qiid );//交司时刻

    // if(jsdt.time() > cTime)
    //     jsdt = jsdt.addDays(1);

    jsdt.setTime(cTime);//指定时刻
    if(now < jsdt) //没到时刻，算上一气
    {
        laterjs = jsdt;
        jsjq -= 4;
        qiid -= 1;
        cTime = _yqjiaosi.time().addSecs( 3600 * SHCH * ( qiid ) );
        beforejs = LIFA::jq2datetime(jsjq);//上次交司
        beforejs.setTime(cTime);
    }
    else
    {
        beforejs = jsdt;
        jsjq += 4;
        laterjs = LIFA::jq2datetime(jsjq);//下次交司
        cTime = _yqjiaosi.time().addSecs( 3600 * SHCH * ( qiid + 1 ) );
        laterjs.setTime(cTime);
    }

    secpart = beforejs.secsTo(now);
    secall = beforejs.secsTo(laterjs);

    _qi6r = qreal(secpart)/secall + qiid;
    _qi = qiid;
}

